//
//  MSScanCodeView.m
//  PeopleForTheFirstMall
//
//  Created by iOS on 2019/9/3.
//  Copyright © 2019 MS. All rights reserved.
//

#import "MSScanCodeView.h"
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>

@interface MSScanCodeView ()
<
AVCaptureMetadataOutputObjectsDelegate
>

@property (nonatomic)           int                         num;
@property (nonatomic)           BOOL                        upOrDown;
@property (nonatomic, strong)   NSTimer                     *timer;
@property (nonatomic, strong)   UIView                      *imgView;
@property (nonatomic, strong)   CAShapeLayer                *cropLayer;         ///< 透明遮罩
@property (nonatomic, strong)   UIView                      *line;              ///< line
@property (nonatomic, strong)   UILabel                     *tipLabel;          ///< 提示语
@property (nonatomic, strong)   AVCaptureDevice             *device;            ///< device
@property (nonatomic, strong)   AVCaptureDeviceInput        *input;             ///< input
@property (nonatomic, strong)   AVCaptureMetadataOutput     *output;            ///< output
@property (nonatomic, strong)   AVCaptureSession            *session;           ///< session
@property (nonatomic, strong)   AVCaptureVideoPreviewLayer  *preview;           ///< Preview


@end

@implementation MSScanCodeView

- (void)ms_bindViewModel
{
    _upOrDown = NO;
    _num = 0;
    
    if (@available(ios 10, *))
    {
        _timer = [NSTimer scheduledTimerWithTimeInterval:0.02 repeats:YES block:^(NSTimer * _Nonnull timer) {
            if (self->_upOrDown == NO)
            {
                self->_num++;
                [self->_line mas_updateConstraints:^(MASConstraintMaker *make) {
                    make.top.mas_equalTo(2 * self->_num);
                }];
                
                if (2 * self->_num >= 370 * MS_ADAPTATION_RATIO)
                {
                    self->_upOrDown = YES;
                }
            }
            else
            {
                self->_num--;
                [self->_line mas_updateConstraints:^(MASConstraintMaker *make) {
                    make.top.mas_equalTo(2 * self->_num);
                }];
                
                if (self->_num <= 0)
                {
                    self->_upOrDown = NO;
                }
            }
        }];
    }
    else
    {
        _timer = [NSTimer scheduledTimerWithTimeInterval:0.02
                                                  target:self
                                                selector:@selector(timerAction)
                                                userInfo:nil
                                                 repeats:YES];
    }
    
    [self visitCamera];
}

- (void)startRunning
{
    if (![_session isRunning])
    {
        [_session startRunning];
        [_timer setFireDate:[NSDate distantPast]];
    }
}

- (void)timerAction
{
    if (_upOrDown == NO)
    {
        _num ++;
        [_line mas_updateConstraints:^(MASConstraintMaker *make) {
            make.top.mas_equalTo(2 * _num);
        }];
        
        if (2 * _num >= 370 * MS_ADAPTATION_RATIO)
        {
            _upOrDown = YES;
        }
    }
    else
    {
        _num --;
        [_line mas_updateConstraints:^(MASConstraintMaker *make) {
            make.top.mas_equalTo(2 * _num);
        }];
        
        if (_num <= 0)
        {
            _upOrDown = NO;
        }
    }
}



#pragma mark AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputMetadataObjects:(NSArray *)metadataObjects
       fromConnection:(AVCaptureConnection *)connection
{
    // 停止扫描
    [_session stopRunning];
    [_timer setFireDate:[NSDate distantFuture]];
    /*
     // 开始扫描
     [_session startRunning];
     [_timer setFireDate:[NSDate distantPast]];
     */
    
    if ([metadataObjects count] > 0)
    {
        AVMetadataMachineReadableCodeObject *metadataObject =  [metadataObjects objectAtIndex:0];
        NSString *stringValue = metadataObject.stringValue;
        
        [self playSystemSound];
        
        MSLog(@"%@", stringValue);
        
        if ([self.delegate performSelector:@selector(scanCodeView:didOutputMetadataObject:)])
        {
            [self.delegate scanCodeView:self
                didOutputMetadataObject:stringValue];
        }
    }
    else
    {
        // 无扫描信息
        if (![_session isRunning])
        {
            [_session startRunning];
            [_timer setFireDate:[NSDate distantPast]];
        }
    }
    
}


#pragma mark - 访问照相机

- (void)visitCamera
{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if (device)
    {
        AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if (status == AVAuthorizationStatusNotDetermined)
        {
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                if (granted)
                {
                    // 用户第一次同意了访问相机权限
                    dispatch_sync(dispatch_get_main_queue(), ^{
                        [self initDevice];
                    });
                }
                else
                {
                    // 用户第一次拒绝了访问相机权限
                    dispatch_sync(dispatch_get_main_queue(), ^{
                        // 停止扫描
                        [self->_session stopRunning];
                        [self->_timer setFireDate:[NSDate distantFuture]];
                        
                        // 用户拒绝了访问相机权限
                        MSLog(@"用户拒绝了访问相机权限");
                    });
                }
            }];
        }
        else if (status == AVAuthorizationStatusAuthorized)
        {
            // 用户允许当前应用访问相机
            [self initDevice];
        }
        else if (status == AVAuthorizationStatusDenied)
        {
            // 用户拒绝当前应用访问相机
            // 请去-> [设置 - 隐私 - 相机 - %@] 开启权限
            MSLog(@"用户拒绝当前应用访问相机");
        }
        else if (status == AVAuthorizationStatusRestricted)
        {
            // 因为系统原因, 无法访问相机
            MSLog(@"因为系统原因, 无法访问相机");
        }
    }
    else
    {
        // 设备没有摄像头
        MSLog(@"设备没有摄像头");
    }
}

- (void)initDevice
{
    // Device
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];;
    // Input
    _input = [[AVCaptureDeviceInput alloc] initWithDevice:_device error:nil];
    // Output
    _output = [[AVCaptureMetadataOutput alloc] init];
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    // 设置扫描区（top 与 left 互换  width 与 height 互换）
    CGRect rect = self.imgView.frame;
    CGFloat top = CGRectGetMinY(rect) / MS_SCREEN_HEIGHT;
    CGFloat left = CGRectGetMinX(rect) / MS_SCREEN_WIDTH;
    CGFloat width = CGRectGetHeight(rect) / MS_SCREEN_WIDTH;
    CGFloat height = CGRectGetWidth(rect) / MS_SCREEN_HEIGHT;
    [_output setRectOfInterest:CGRectMake(top, left, height, width)];
    
    // Session
    _session = [[AVCaptureSession alloc] init];
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    // 添加输入流
    if ([_session canAddInput:_input])
    {
        [_session addInput:_input];
    }
    // 添加输出流
    if ([_session canAddOutput:_output])
    {
        [_session addOutput:_output];
    }
    
    // 设置条码类型
    _output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code,
                                    AVMetadataObjectTypeEAN8Code,
                                    AVMetadataObjectTypeCode128Code,
                                    AVMetadataObjectTypeQRCode];
    // Preview
    _preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _preview.frame = self.layer.bounds;
    [self.layer insertSublayer:_preview atIndex:0];
    
    // Start
    [_session startRunning];
}


#pragma mark - PalySound

- (void)playSystemSound
{
    // 当参数为:kSystemSoundID_Vibrate 时就是震动;当参数为 1000-2000 之间数字时就是播放系统声音
    SystemSoundID soundID = 1000;
    
    AudioServicesPlaySystemSoundWithCompletion(soundID, ^{
        
    });
}

- (void)playSoundName:(NSString *)name
{
    NSString *audioFile = [[NSBundle mainBundle] pathForResource:name ofType:nil];
    NSURL *fileUrl = [NSURL fileURLWithPath:audioFile];
    
    SystemSoundID soundID = 0;
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(fileUrl), &soundID);
    AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, playSoundCompleteCallback, NULL);
    AudioServicesPlaySystemSound(soundID); // 播放音效
}

void playSoundCompleteCallback(SystemSoundID soundID, void *clientData){
    // 播放成功回调
}

- (void)ms_setupSubViews
{
    [self addSubview:self.imgView];
    
    [self.imgView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.size.mas_equalTo(CGSizeMake(370 * MS_ADAPTATION_RATIO,
                                         370 * MS_ADAPTATION_RATIO));
    }];
    
    [self.imgView addSubview:self.line];
    
    [self.line mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(0);
        make.centerX.equalTo(self.imgView);
        make.size.mas_equalTo(CGSizeMake(370 * MS_ADAPTATION_RATIO,
                                         10 * MS_ADAPTATION_RATIO));
    }];
    
    [self addSubview:self.tipLabel];
    
    [self.tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self);
        make.centerX.equalTo(self);
    }];
    
    [self layoutIfNeeded];
    [self setCropRect:self.imgView.frame];
}

- (void)setCropRect:(CGRect)cropRect
{
    _cropLayer = [[CAShapeLayer alloc] init];
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, nil, cropRect);
    CGPathAddRect(path, nil, self.bounds);
    
    [_cropLayer setFillRule:kCAFillRuleEvenOdd];
    [_cropLayer setFillColor:[UIColor blackColor].CGColor];
    [_cropLayer setOpacity:0.65f];
    [_cropLayer setPath:path];
    
    [_cropLayer setNeedsDisplay];
    CGPathRelease(path);
    
    [self.layer addSublayer:_cropLayer];
}


#pragma mark - lazy loading

- (UIView *)imgView
{
    if (!_imgView)
    {
        _imgView = [[UIView alloc] init];
        _imgView.layer.contents = (id)[UIImage imageNamed:@"QRCode_pick_bg"].CGImage;
    }
    
    return _imgView;
}

- (UIView *)line
{
    if (!_line)
    {
        _line = [[UIView alloc] init];
        _line.layer.contents = (id)[UIImage imageNamed:@"QRCode_line"].CGImage;
    }
    
    return _line;
}

- (UILabel *)tipLabel
{
    if (!_tipLabel)
    {
        _tipLabel = [[UILabel alloc] init];
        _tipLabel.font = [UIFont systemFontOfSize:14];
        _tipLabel.textColor = MS_HEX_COLOR(0xffc548);
        _tipLabel.text = @"将二维码/条形码放入框内，即可自动扫描";
    }
    
    return _tipLabel;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:CGRectMake(0,
                                           0,
                                           MS_SCREEN_WIDTH,
                                           MS_SCREEN_HEIGHT)];
    if (self) {
        
    }
    return self;
}


/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end
